/******************************************************************************* * Signavio Core Components * Copyright (C) 2012 Signavio GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package de.hpi.bpmn2_0.factory.node; import org.oryxeditor.server.diagram.generic.GenericShape; import de.hpi.bpmn2_0.annotations.Property; import de.hpi.bpmn2_0.annotations.StencilId; import de.hpi.bpmn2_0.exceptions.BpmnConverterException; import de.hpi.bpmn2_0.factory.AbstractActivityFactory; import de.hpi.bpmn2_0.factory.AbstractBpmnFactory; import de.hpi.bpmn2_0.factory.BPMNElement; import de.hpi.bpmn2_0.factory.configuration.Configuration; import de.hpi.bpmn2_0.factory.configuration.LinkedModel; import de.hpi.bpmn2_0.model.AdHocOrdering; import de.hpi.bpmn2_0.model.BaseElement; import de.hpi.bpmn2_0.model.Definitions; import de.hpi.bpmn2_0.model.FlowElement; import de.hpi.bpmn2_0.model.FormalExpression; import de.hpi.bpmn2_0.model.Process; import de.hpi.bpmn2_0.model.activity.Activity; import de.hpi.bpmn2_0.model.activity.AdHocSubProcess; import de.hpi.bpmn2_0.model.activity.CallActivity; import de.hpi.bpmn2_0.model.activity.SubProcess; import de.hpi.bpmn2_0.model.activity.Transaction; import de.hpi.bpmn2_0.model.activity.TransactionMethod; import de.hpi.bpmn2_0.model.artifacts.Artifact; import de.hpi.bpmn2_0.model.bpmndi.BPMNShape; import de.hpi.bpmn2_0.model.extension.signavio.SignavioMetaData; import de.hpi.bpmn2_0.transformation.Diagram2BpmnConverter; /** * Factory to handle all types subprocesses in a process diagram * * @author Sven Wagner-Boysen * */ @StencilId({ "CollapsedSubprocess", "Subprocess", "CollapsedEventSubprocess", "EventSubprocess" }) public class SubprocessFactory extends AbstractActivityFactory { // @Override public BPMNElement createBpmnElement(GenericShape shape, Configuration configuration) throws BpmnConverterException { BPMNElement bpmnElement = super.createBpmnElement(shape, configuration); if(bpmnElement != null && bpmnElement.getNode() != null) { handleLinkedDiagrams(bpmnElement.getNode(), shape, configuration); } return bpmnElement; } // @Override protected BPMNShape createDiagramElement(GenericShape shape) { BPMNShape bpmnShape = super.createDiagramElement(shape); /* Mark as collapsed or expanded */ if(shape.getStencilId().matches(".*Collapsed.*")) { bpmnShape.setIsExpanded(false); } else { bpmnShape.setIsExpanded(true); } return bpmnShape; } /* (non-Javadoc) * @see de.hpi.bpmn2_0.factory.AbstractBpmnFactory#createProcessElement(org.oryxeditor.server.diagram.Shape) */ // @Override protected BaseElement createProcessElement(GenericShape shape) throws BpmnConverterException { Activity subprocess = null; try { subprocess = (Activity) this.invokeCreatorMethodAfterProperty(shape); this.createLoopCharacteristics(subprocess, shape); } catch (Exception e) { // throw new BpmnConverterException("Error creating subprocess elements.", e); } if(subprocess == null) subprocess = new SubProcess(); this.setStandardAttributes(subprocess, shape); /* Mark as event subprocess */ if(!(subprocess instanceof CallActivity)) { if(shape.getStencilId().matches(".*EventSubprocess.*")) { ((SubProcess) subprocess).setTriggeredByEvent(true); } else { ((SubProcess) subprocess).setTriggeredByEvent(false); } } subprocess.setName(shape.getProperty("name")); return subprocess; } @Property(name = "callacitivity", value = "true") public CallActivity createCallActivity(GenericShape shape) { CallActivity callAct = new CallActivity(); this.setStandardAttributes(callAct, shape); return callAct; } @Property(name = "isatransaction", value = "true") public Transaction createTransaction(GenericShape shape) { Transaction transaction = new Transaction(); transaction.setMethod(TransactionMethod.fromValue(shape.getProperty("transactionMethod"))); return transaction; } @Property(name = "isadhoc", value = "true") public AdHocSubProcess createAdhocSubprocess(GenericShape shape) { AdHocSubProcess adhocSub = new AdHocSubProcess(); /* Mapping of properties */ String condition = shape.getProperty("adhoccompletioncondition"); if(condition != null && !(condition.length() == 0)) adhocSub.setCompletionCondition(new FormalExpression(condition)); String ordering = shape.getProperty("adhocordering"); if(ordering != null) { adhocSub.setOrdering(AdHocOrdering.fromValue(shape.getProperty("adhocordering"))); } String cancelRemIns = shape.getProperty("adhoccancelremaininginstances"); if(cancelRemIns != null) adhocSub.setCancelRemainingInstances(!cancelRemIns.equalsIgnoreCase("false")); return adhocSub; } /** * Transforms linked diagrams of collapsed subprocess and event subprocess. * * @param baseElement * @param shape * @param config */ private void handleLinkedDiagrams(BaseElement baseElement, GenericShape shape, Configuration config) { if(baseElement == null || !((baseElement instanceof SubProcess) || (baseElement instanceof CallActivity)) || !shape.getStencilId().matches(".*Collapsed.*")) { return; } /* * Diagram Link */ String entry = shape.getProperty("entry"); if(entry == null || entry.length() == 0) { return; } SignavioMetaData metaData = new SignavioMetaData("entry", entry); baseElement.getOrCreateExtensionElements().add(metaData); Definitions linkedDiagram = retrieveDefinitionsOfLinkedDiagram(entry, config); if(linkedDiagram == null || linkedDiagram.getRootElement().size() == 0) { return; } /* * Handle call activity */ if(baseElement instanceof CallActivity) { CallActivity ca = (CallActivity) baseElement; /* * Assign called process as called element */ for(BaseElement rootEl : linkedDiagram.getRootElement()) { if(rootEl instanceof Process) { Process p = (Process) rootEl; ca.setCalledElement(p); break; } } if(linkedDiagram.getDiagram().size() > 0) { ca._diagramElement = linkedDiagram.getDiagram().get(0); } return; } /* * Handle sub process */ SubProcess subProcess = (SubProcess) baseElement; for(BaseElement rootEl : linkedDiagram.getRootElement()) { if(rootEl instanceof Process) { Process p = (Process) rootEl; subProcess.getFlowElement().addAll(p.getFlowElement()); subProcess.getArtifact().addAll(p.getArtifact()); } } /* Retrieve diagram elements */ for(FlowElement element : subProcess.getFlowElement()) { subProcess._diagramElements.add(element._diagramElement); // if(element instanceof SubProcess) { // subProcess._diagramElements.addAll(((SubProcess) element)._diagramElements); // } } for(Artifact artifact : subProcess.getArtifact()) { subProcess._diagramElements.add(artifact._diagramElement); } } /** * Calculation the BPMN 2.0 Definitions element of the linked diagram. * * @return */ protected static Definitions retrieveDefinitionsOfLinkedDiagram(String url, Configuration configuration) { int lastSlashIndex = url.lastIndexOf("/"); LinkedModel linkedModel = configuration.getLinkedModels().get(url.substring(lastSlashIndex + 1)); if(linkedModel == null || linkedModel.getDiagram() == null || !linkedModel.getDiagram().getStencilsetRef().getNamespace().matches("http://b3mn\\.org/stencilset/bpmn2\\.0.*")) { return null; } Diagram2BpmnConverter converter = new Diagram2BpmnConverter(linkedModel.getLinkedModels(), linkedModel.getDiagram(), AbstractBpmnFactory.getFactoryClasses()); try { return converter.getDefinitionsFromDiagram(); } catch (BpmnConverterException e) { e.printStackTrace(); return null; } } }